# 取出数据库中所有的订单 id。扩充时，在订单id后加"_{重复次数}"
from ws4py.client.threadedclient import WebSocketClient
import json, threading, time
import numpy as np
import pandas as pd

class SupplierClient(WebSocketClient):

    def __init__(self, url, supplier_id, lon, lat):
        super().__init__(url)
        self.supplier_id = supplier_id
        self.lon = lon
        self.lat = lat
        self.final_selected_demand_id = "none"
        self.final_selected_time = 20
        self.timer = None

    def cancel(self):
        self.close()

    def opened(self):  # socket连接后调用
        print("open!")

    def closed(self, code, reason=None):  # wk关闭时调用
        print(code, time.strftime('%Y-%m-%d %H:%M:%S'))

    def received_message(self, message):  # 长连接时接收socket的所有消息,可根据消息做对应处理
        if str(message) == "online":
            return
        if str(message) == "success":
            print("get a demand")
            self.close()
            return
        if str(message) == "round_ended":
            print("round_ended")
            if not self.timer is None:
                self.timer.cancel()
            return
        if str(message) == "failed":
            print("failed")
            return
        self.respond(str(message))

    def respond(self, json_string):
        self.final_selected_demand_id = "none"
        self.final_selected_time = 20
        demands_infos = json.loads(json_string)
        for demand_info in demands_infos:
            selected_time = self.round_select(demand_info['probabilities'])
            if selected_time < self.final_selected_time:
                self.final_selected_time = selected_time
                self.final_selected_demand_id = demand_info['id']
        # if self.supplier_id == "hk_4396+1":
        #     self.final_selected_time = 0;
        if self.final_selected_demand_id != "none":
            print(str(self.supplier_id) + "will select " + self.final_selected_demand_id + "at time " + str(self.final_selected_time))
            self.timer = threading.Timer(self.final_selected_time, self.select_demand)
            self.timer.start()
        else:
            print(str(self.supplier_id) + "will not select any demands.")

    def round_select(self, one_to_one_probs):
        select_demand_prob_part = np.random.rand()
        prob_total = 0.0
        prob_index = 0
        selected_time = 20;
        for prob in one_to_one_probs:
            prob_total += prob
            if prob_total > select_demand_prob_part:
                selected_time = prob_index
                break
            prob_index += 1
        return selected_time

    def select_demand(self, ):
        self.send(json.dumps({"type": "select_demand",
            "supplier_id": self.supplier_id,
            "demand_id": self.final_selected_demand_id
        }))
        print(str(self.supplier_id) + "selects " + self.final_selected_demand_id + "at time " + str(
            self.final_selected_time))


def start_supplier(supplier_id, lon, lat):
    ws = SupplierClient("ws://localhost:8090/websocket/supplier/" + supplier_id, supplier_id, lon, lat)
    message = json.dumps({
        "type": "info",
        "id": supplier_id,
        "lon": lon,
        "lat": lat
    })
    ws.connect()
    ws.send(message)
    ws.run_forever()


if __name__ == '__main__':
    appear_num_max = 2;
    appear_prob = 0.3
    supplier_id_dic = {}
    supplier_infos = pd.read_csv("data/supplier_loc.csv").values
    supplier_info_length = len(supplier_infos)
    while True:
        if np.random.rand() > appear_prob:
            time.sleep(1)
            continue
        supplier_num = int(np.random.rand() * appear_num_max)
        for i in range(supplier_num):
            supplier_info = supplier_infos[int(np.random.rand() * supplier_info_length)]
            if supplier_info[0] in supplier_id_dic.keys():
                supplier_id_dic[supplier_info[0]] += 1
            else:
                supplier_id_dic[supplier_info[0]] = 1
            th = threading.Thread(target=start_supplier, args=(supplier_info[0] + "+" + str(supplier_id_dic[supplier_info[0]]),
                                                               float(supplier_info[2]),
                                                               float(supplier_info[1])))
            th.start()
        time.sleep(1)

    # th = threading.Thread(target=start_supplier,
    #                       args=("hk_5629+1",
    #                             114.17121000000002,
    #                             22.3249331))
    # th.start()
    #
    # time.sleep(1)
    #
    # th = threading.Thread(target=start_supplier,
    #                       args=("hk_5629+2",
    #                             114.0590677,
    #                             22.3678527))
    # th.start()
    # time.sleep(1)
    #
    # th = threading.Thread(target=start_supplier,
    #                       args=("hk_4396+1",
    #                             114.1783517,
    #                             22.2519317))
    # th.start()

    # time.sleep(1)
    #
    # th = threading.Thread(target=start_supplier,
    #                       args=("hk_4396+2",
    #                             114.1956285,
    #                             22.3344787))
    # th.start()